package de.hm.edu.chartservice;

import java.math.BigDecimal;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.UUID;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import de.hm.edu.kpi.Axis;
import de.hm.edu.kpi.KeyIndicator;
import de.hm.edu.kpi.LineChart;
import de.hm.edu.kpi.LineValueSeries;
import de.hm.edu.kpi.ObjectFactoryImpl;
import de.hm.edu.kpi.Point;

/**
 * A Singleton Class representing the Product Share KPI
 * 
 * @author Peter Goldenbogen (Munich University of Applied Science)
 * @version 1.0 
 */
public class SalesVolume {
	
	/**ProductShare Singleton Instance*/
	private static SalesVolume instance = null;
	/**A nested key Indicator object*/
	private static KeyIndicator keyIndicator;
	/**key Indicator title*/
	private static String title = "Sales Amount Line Chart";
	/**key Indicator description*/
	private static String description = "A line chart representing the total amount of all products sold within the last hour";
	/**The max amount of orders that will be added to the Sales Volume line chart*/
	private final int WINDOWSIZE = 100;
	private SalesVolume() {}

	/**
	 * Initializes the KPI object parameters  and data
	 * @return a SalesVolume singleton instance
	 */
	public static SalesVolume getInstance(){
		if (instance == null){
			instance = new SalesVolume();
			ObjectFactoryImpl oFactory = new ObjectFactoryImpl();
			
			//Init SalesAmount Object
			keyIndicator = oFactory.createKeyIndicator();
			keyIndicator.setTitle(title);
			keyIndicator.setDescription(description);
			keyIndicator.setIdentifier(UUID.randomUUID().toString());
			keyIndicator.setCreationTime(getXMLGregTimestamp());
			keyIndicator.setDataPeriodStart(getXMLGregTimestamp());
			
			//create Axis
			Axis time = oFactory.createAxis();
			time.setTitle("Time");
			Axis amount = oFactory.createAxis();
			amount.setTitle("Amount");
			amount.setMinAxisValue(new BigDecimal(0));
			
			//create Value Series
			LineValueSeries	lvs = oFactory.createLineValueSeries();
			lvs.setTitle("Sold Products");

			for(int currentMinute = 0; currentMinute < instance.WINDOWSIZE; currentMinute++){
				Point p = oFactory.createPoint();
				p.setYValue(new BigDecimal(0));
				p.setXValue(new BigDecimal(System.currentTimeMillis()));
				lvs.getPoint().add(p);
			}
			
			LineChart line = oFactory.createLineChart();
			line.getAxis().add(time);
			line.getAxis().add(amount);
			line.getLineValueSeries().add(lvs);
			keyIndicator.setPieChartOrLineChart(line);
		}
		
		return instance;
	}
	
	/**
	 * Updates the KPI data
	 * @param amount the amount that will be added to sales volume
	 */
	public void update(int amount){
		
		LineChart line = (LineChart) getInstance().getKeyIndicator().getPieChartOrLineChart();
		
		Point newPoint = new Point();
		newPoint.setXValue(new BigDecimal(System.currentTimeMillis()));
		newPoint.setYValue(new BigDecimal(amount));
		
		//find oldest Pointelement
		List<Point> points = line.getLineValueSeries().get(0).getPoint();
		int i = 0;
		Point first = points.get(0);
		for(Point point: points){
			if(point.getXValue().compareTo(first.getXValue()) == -1){
				i = points.indexOf(point);
			}
		}
		
		//Set new Point at the index of the oldest element
		line.getLineValueSeries().get(0).getPoint().set(i, newPoint);
		
		getInstance().getKeyIndicator().setDataPeriodEnd(getXMLGregTimestamp());
		getInstance().getKeyIndicator().setPieChartOrLineChart(line);
	}
		
	/**
	 * Creates a XMLGregorian timestamp
	 * @return XMLGregorian object with the current time and date.
	 */
	private static XMLGregorianCalendar getXMLGregTimestamp() {
		//Update DataTimeFrame in ProductShare chart instance
    	GregorianCalendar gregCal = new GregorianCalendar();
    	gregCal.setTime(new Date(System.currentTimeMillis()));
    	XMLGregorianCalendar xmlGregCal = null;
    	try {
			xmlGregCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(gregCal);
		} catch (DatatypeConfigurationException e) {
			e.printStackTrace();
		}
		return xmlGregCal;
	}
	
	public KeyIndicator getKeyIndicator(){
		return keyIndicator;
	}
}
